<?php
/**
 * QueryWrapper
 * Static class for executing sql scripts to mysql
 * @author Joona Somerkivi <joona@somerkivi.net>
 */
abstract class Lib_QueryWrapper {

    private static $ready = false;

    private static $dbUser;
    private static $dbPassword;
    private static $dbName;
    private static $dbHost;

    /**
     * Setup the QueryWrapper
     * @param string $dbUser
     * @param string $dbPassword
     * @param string $dbName
     * @param string $dbHost
     */
    public static function setUp(
            $dbUser = 'root',
            $dbPassword = null,
            $dbName = 'test_sweatshop',
            $dbHost = 'localhost')
    {
        self::$dbUser = $dbUser;
        self::$dbPassword = $dbPassword;
        self::$dbName = $dbName;
        self::$dbHost = $dbHost;
        
        self::$ready = true;
    }

    private static function isReady()
    {
        return self::$ready;
    }

    /**
     * Run bash command that executes given script with mysql
     * If setUp() is not runned yet, this will run it with default values
     * @param string $scriptToRun Name of the script in Test/Lib/scripts/ folder
     * @throws Lib_QueryWrapper_Exception on SQL error
     */
    public static function runScript($scriptToRun, $skipDatabaseName = false)
    {
        self::isReady() || self::setUp();

        $actualScript = dirname(__FILE__)."/scripts/$scriptToRun.sql";
        if(!file_exists($actualScript))
            throw new Lib_QueryWrapper_Exception("Missing script '$scriptToRun' from Lib/scripts/");
        $command = self::formBashCommantToRunScript($actualScript, $skipDatabaseName);
        $output = passthru($command, $successCode);
        if($successCode != 0)
            throw new Lib_QueryWrapper_Exception($output);
    }

    /**
     * Run bash command that executes given query with mysql
     * If setUp() is not runned yet, this will run it with default values
     * @param string $scriptToRun Name of the script in Test/Lib/scripts/ folder
     * @return array If result set contains values array(column => value), empty
     * array if no results found
     * @throws Lib_QueryWrapper_Exception on SQL error
     */
    public static function runQuery($queryToRun, $skipDatabaseName = false)
    {
        self::isReady() || self::setUp();

        $command = self::formBashCommantToRunQuery($queryToRun, $skipDatabaseName);
        exec($command, $output, $resultCode);
        if($resultCode != 0)
            throw new Lib_QueryWrapper_Exception(implode("\n", $output));

        if(!array_key_exists(0, $output))
            return array();
        
        $keys = explode("\t", $output[0]);
        $result = array();
        for($row = 1; $row < sizeof($output) ; $row++)
        {
            $values = explode("\t", $output[$row]);
            $rowResult = array();
            foreach($keys as $index => $key)
                $rowResult[$key] = $values[$index];
            $result[] = $rowResult;
        }
        return $result;
    }
    
    public static function initializeTestData()
    {
        self::runScript('testDataDump');
    }
    
    public static function createTestDatabase()
    {
        self::runQuery('DROP DATABASE IF EXISTS '.self::$dbName, true);
        self::runQuery('CREATE DATABASE '.self::$dbName, true);
        self::runScript('create-database');
        self::initializeTestData();
    }

    public static function dropTestDatabase()
    {
        //self::runScript('teardown');
        self::runQuery('DROP DATABASE IF EXISTS '.self::$dbName);
    }

    private static function formBashCommantToRunScript($scriptToRun, $skipDatabaseName = false)
    {
        return implode(' ', array(
           'mysql',
            '-h ' , self::$dbHost,
            '-u ', self::$dbUser,
            is_null(self::$dbPassword) ? '' : '-p'.self::$dbPassword,
            $skipDatabaseName ? '' : self::$dbName,
            '<',
            $scriptToRun
        ));
    }

    private static function formBashCommantToRunQuery($queryToRun, $skipDatabaseName = false)
    {
        $escapedQuery = escapeshellarg($queryToRun);
        return implode(' ', array(
            "echo $escapedQuery",
            '|',
            'mysql',
            '-h ' , self::$dbHost,
            '-u ', self::$dbUser,
            is_null(self::$dbPassword) ? '' : '-p'.self::$dbPassword,
            $skipDatabaseName ? '' : self::$dbName
        ));
    }
}
class Lib_QueryWrapper_Exception extends Exception {}
